// "Copyright [2021] <Copyright Han>"
#include "controllerAdapter.h"
#include "../ai_sim.h"
namespace ai_sim {
Define_Module(controllerAdapter);


void controllerAdapter::handleMessage(omnetpp::cMessage *msg) {
    if (msg->arrivedOn("configuration_port")) {
        // 如果是来自configurator的消息,那么记录相关映射关系
        EV_INFO << "adapters receive configuration information" << "\n";
        ACLMsg *a_pk = dynamic_cast<ACLMsg *>(msg);
        unsigned int address = a_pk->getAddressInt();
        unsigned int netmask = a_pk->getNetmaskInt();
        const char * interfacename = a_pk->getModuleName();
        IpAddressMap[a_pk->getOutportGateId()] = address;
        NetmaskMap[a_pk->getOutportGateId()] = netmask;
        outputGateInterfaceMap[a_pk->getOutportGateId()] = a_pk->getLocalId();
        inputGateInterfaceMap[a_pk->getInportGateId()] = a_pk->getLocalId();
        for(int i=0;i<strlen(interfacename);++i){
            EV_INFO <<interfacename[i];
        }
        EV_INFO << "\n";
        delete a_pk;
    }
    else if(msg->arrivedOn("controller_port")){
        // 如果是来自controller的消息,那么根据到来的message向router发送流表
        EV_INFO << "adapters receive controller information" << "\n";
        ai_sim::RouteVecMsg *ra_msg = dynamic_cast<ai_sim::RouteVecMsg *> (msg);
        unsigned int switchIndex = ra_msg->getIndex();
        unsigned int tempIndex = 0;
        for (auto routes : ra_msg->getNew_route_table()) {
            unsigned int outPort =  outputGateInterfaceMap[routes.outPort];
            unsigned int inPort = inputGateInterfaceMap[routes.inPort];
            unsigned int srcIdx = routes.srcIdx;
            unsigned int destIdx = routes.destIdx;
            tempIndex += 1;
            unsigned int tempoutPortAddressInt = IpAddressMap[routes.outPort];
            sendSingleFlow(switchIndex, srcIdx, destIdx,tempoutPortAddressInt,inPort, outPort, -1, -1);
        }
        delete ra_msg;

    }
    else {
        delete msg;
        throw omnetpp::cRuntimeError("Unknown gate");
    }
}


void controllerAdapter::sendSingleFlow(int switch_ID, unsigned int SourceAddress, unsigned int DestAddress, unsigned int NextHopAddress,
        int inPort,  int interfaceID, int priority, int protocolID){
    Enter_Method("sendSingleFlow");
    // send message to router
    ACLSingleEntry *tmp_acl_entry_msg = new ACLSingleEntry;
    tmp_acl_entry_msg -> setSourceAddressInt(SourceAddress);
    tmp_acl_entry_msg -> setDestAddress(DestAddress);
    tmp_acl_entry_msg -> setNextHopAddress(NextHopAddress);
    tmp_acl_entry_msg -> setSourcePort(inPort);
    tmp_acl_entry_msg -> setInterfaceID(interfaceID);
    tmp_acl_entry_msg -> setPriority(priority);
    tmp_acl_entry_msg -> setProtocolID(protocolID);
    send(tmp_acl_entry_msg, "switch_port$o", switch_ID);

}
}

